/*
var name = "";
function show(){

}
alert(name)
show();

function Person(name){
    this.name = name;
    this.show=function(){
        console.log("~~~")
    }
}
var per = new Person();
per.name= "";
per.show()
*/

/**
 * 实现继承方式一：
 *   原型链实现：将父类对象赋值给子类原型。这样子类实例对象
 */
/*
function Father(){
    //this.house = "房产";
}
Father.prototype.money = "一亿";
function Son(){
}
//继承
Son.prototype = new Father();
//实力化Son
var son1 = new Son();
console.log(son1.money);
console.log(son1.house);
*/
/**
 * 实现继承方式二：
 *   原型链实现：将父类原型赋值给子类原型。这样子类实例对象
 */
/*
function Father(){
    this.house = "房产";
}
Father.prototype.money = "一亿";
function Son(){
}
//继承
Son.prototype = Father.prototype;//子类prototype就指向了父类prototype。[父类子类的prototype都指向同一处内存地址]
//实力化Son
var son1 = new Son();
console.log(son1.money);
console.log(son1.house);

//son1.money = "1百万";//对象中的数据
//son1.prototype.money = "1百万";  对象是没有prototype属性；构造函数才有prototype属性
son1.__proto__.money = "1百万";

console.log(son1.money);

var fa = new Father();
console.log(fa.money);
*/

/**
 * 实现继承方式三：
 *   原型链实现：将父类原型赋值给空对象，再将空对象赋给子类原型。
 */
/*
function Father(){

}
Father.prototype.money = "一亿";
function Son(){
}
//将父类原型赋值给另一对象
var Fn = function(){};
// function Fn(){
// }
// 继承
Fn.prototype = Father.prototype
Son.prototype = new Fn()
//改构造函数
Son.prototype.constructor = Son;

//实力化Son
var son1 = new Son();
console.log(son1.money);
son1.__proto__.money = "1百万";
console.log(son1.money);

var fa = new Father();
console.log(fa.money);

console.log(son1.constructor);
console.log(fa.constructor);
*/

/**
 * 实现继承方式四：
 *   子类通过call()或apply()方法借调父类构造函数
 */
/*
function Father(name,age){
    this.name=name;
    this.age = age;
    this.test=function(){
        console.log("test!")
    }
}
Father.prototype.show=function(){
    console.log(this.name,this.age);
}

function Son(){
    //Father.call(this,'zhangsan',18);
    Father.apply(this,['zhangsan',18]);
}
var mySon = new Son();
console.log(mySon.name)
console.log(mySon.age)
mySon.test();
mySon.show();
*/

/**
 * 实现继承方式五：组合继承
 *   子类通过call()或apply()方法借调父类构造函数，获取实例数据
 *   子类通过prototype获取原型数据
 */
/*
function Father(name,age){
    this.name=name;
    this.age = age;
    this.test=function(){
        console.log("test!")
    }
}
Father.prototype.show=function(){
    console.log(this.name,this.age);
}

function Son(){
    //Father.call(this,'zhangsan',18);
    Father.apply(this,['zhangsan',18]);//获取构造函数里数据 
}
var F = function(){};
F.prototype = Father.prototype; //获取原型数据
Son.prototype = new F();

var mySon = new Son();
console.log(Son.prototype.constructor)
console.log(mySon.name)
console.log(mySon.age)
mySon.test();
mySon.show();
*/

/**
 * 实现继承方式六：拷贝继承
       将父类原型中的所有特征获取并循环赋值给子类原型
 */
/*
function Father(name,age){
    //实例数据
    this.name=name;
    this.age=age;   
}
Father.prototype.sex='男';
Father.prototype.show=function(){
    console.log("函数");
    //console.log(this.name,this.age);
}

function Son(){
}

function gongneng(f,s){
    //console.log(f.prototype.constructor)
    var fa = f.prototype;
    var son = s.prototype;

    //循环原型对象的属性或函数等特征
    for(var key in fa){
        //console.log(key,fa[key]);
        son[key] = fa[key];
    }
    console.log(Son.prototype);
}
gongneng(Father,Son);

console.log(Son.prototype);

var mySon = new Son();
console.log(mySon.sex);
mySon.show();
*/

/**
 * 多态：编译时和运行时结果不同
 */
//（1）同一个构造函数中，方法名相同，参数列表不同
//构造函数内的同名函数会覆盖。从而失去多态的效果
// function Student(){
//     this.show = function(){
//         console.log('show1');
//     }
//     this.show = function(str){
//         console.log('show2');
//     }
// }
// //实例化对象
// var stu = new Student();
// stu.show();
// stu.show("a");

//（2）在父子类中，子类方法与父类方法用名，优先调用子类的
//构造函数内的同名子类函数会覆盖同名父类函数，从而失去多态的效果。
/*
function Father(){
    this.show = function(){
        console.log('father');
    }
}
function Son(){
    this.show = function(){
        console.log('son');
    }
}
Son.prototype = new Father();
var son = new Son();
son.show();
*/

//（3）编译时和运行时结果不同
//JS变量没类型，无法识别父类子类，从而失去多态的效果。
/*
function Father(){
    this.show = function(){
        console.log('father');
    }
}
function Son(){
    this.show = function(){
        console.log('son');
    }
}
function HanShu(Father){

    return new Son();
}
*/

//函数表达式会根据不同的调用时刻，来赋值不同的函数值

/*
function fn(){
    alert(1);
}
fn();
function fn(){
    alert(2);
}
fn();
*/

var fn = function(){
    alert(1)
}
fn();
var fn = function(){
    alert(2)
}
fn();